var map;
var geocoder;
var infowindow;
var infobox;

var selectedDistrict;
var currentDistrict; //for time dropdown

var address_position = 0;
var period = "a";//keeps selected interval

var pos = new Array();//position of districts
var districts = new Array();//city districts polygons
var markersArray = new Array();//markers currently displayed on map
var allFires = new Array();//all fires included in fires.xml
var fireIndicesByPeriod = new Array();//indices of allFires which meet the filter
var allPositions = new Array();//positions of all fire from fires.xml


/**
 * Initializes Google maps, loads necessery data and centers the map on initial position.
 */
function initialize() {
    loadData();

    var mapOptions = {
        center: pos["kralovopole"],
        zoom: 14,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        streetViewControl: false
    };
    geocoder = new google.maps.Geocoder();
    map = new google.maps.Map(document.getElementById("map-canvas"),
            mapOptions);
    districts["kralovopole"].setMap(map);
    selectedDistrict = districts["kralovopole"];
    runJQuery();
    currentDistrict = "kralovopole";
    addDropDown("combobox");
    addDropDown("container");
    markThisDistrict(currentDistrict);
}
google.maps.event.addDomListener(window, 'load', initialize);

/**
 * Centers map on selected district.
 * 
 * @param value selected district
 */
function center(value) {
    selectedDistrict.setMap(null);
    if (value == "all") {
        map.setCenter(pos[value]);
        districts["sever2"].setMap(null);
        return;
    }
    map.setCenter(pos[value]);
    if (districts[value] == districts["sever"]) {
        districts["sever1"].setMap(map);
        districts["sever2"].setMap(map);
        selectedDistrict = districts["sever1"];
    }
    else {
        districts[value].setMap(map);
        selectedDistrict = districts[value];
        districts["sever2"].setMap(null);
    }
}

/**
 * Adds clickable marker on the map with specified info.
 * 
 * @param location map positions
 * @param title    marker title
 * @param desc     html code for the popup window when marker is clicked
 */
function addMarker(location, title, desc) {
    var marker = new google.maps.Marker({
        position: location,
        map: map,
        title: title,
        icon: 'images/fire-marker.png',
        clickable: true
    });
    //console.log('pridane: '+title);
    markersArray.push(marker);
    // Adds listner for marker, Infowindow will be open on marker click
//    google.maps.event.addListener(marker, "click", function() {
//        if (infowindow)
//            infowindow.close();
//        infowindow = new google.maps.InfoWindow({
//            content: desc,
//            maxWidth: 100
//        });
//        infowindow.open(map, marker);
//    });
  
//    var boxText = document.createElement("div");
//    boxText.setAttribute("id","infobox");
//    //boxText.style.cssText = "border: 1px solid black; margin-top: 8px; background: yellow; padding: 5px;";
//    boxText.innerHTML = "Testujem infobox";
//
//    var myOptions = {
//        content: boxText
//                , disableAutoPan: false
//                , maxWidth: 0
//                , pixelOffset: new google.maps.Size(-140, 0)
//                , zIndex: null
//                , boxStyle: {
//            background: "url('tipbox.gif') no-repeat"
//                    , opacity: 0.75
//                    , width: "280px"
//        }
//        , closeBoxMargin: "10px 2px 2px 2px"
//                , closeBoxURL: "http://www.google.com/intl/en_us/mapfiles/close.gif"
//                , infoBoxClearance: new google.maps.Size(1, 1)
//                , isHidden: false
//                , pane: "floatPane"
//                , enableEventPropagation: false
//    };
    
    google.maps.event.addListener(marker, "click", function(e) {
        if (infobox) {
            infobox.close();
        }
        addElement(desc);
         infobox = new InfoBox({
         content: document.getElementById("infobox"),
         disableAutoPan: false,
         maxWidth: 150,
         pixelOffset: new google.maps.Size(-140, 0),
         zIndex: null,
         boxStyle: {
            background: "url('http://google-maps-utility-library-v3.googlecode.com/svn/trunk/infobox/examples/tipbox.gif') no-repeat",
            opacity: 0.75,
            width: "280px"
        },
        closeBoxMargin: "12px 4px 2px 2px",
        closeBoxURL: "http://www.google.com/intl/en_us/mapfiles/close.gif",
        infoBoxClearance: new google.maps.Size(1, 1)
    });
        infobox.open(map, this);
    });

    //ib.open(map, marker);
}
/**
 * Adds element for the infobox windows.
 * 
 * @param text text inside the infobox
 */
function addElement(text) {

  var ni = document.getElementById('myDiv');
  var newdiv = document.createElement('div');

  newdiv.setAttribute('id',"infobox");
  newdiv.innerHTML = text;

  ni.appendChild(newdiv);
}

/**
 * Shows any overlays currently in the array.
 * 
 */
function showOverlays() {
    if (markersArray) {
        for (i in markersArray) {
            markersArray[i].setMap(map);
        }
    }
}

/**
 * Deletes all markers in the array by removing references to them.
 * 
 */
function deleteOverlays() {
    if(infobox) {
        infobox.close();
    }
    if (markersArray) {
        for (i in markersArray) {
            markersArray[i].setMap(null);
        }
        markersArray.length = 0;
    }
}

/**
 * Removes the overlays from the map, but keeps them in the array.
 * 
 */
function clearOverlays() {
    if (markersArray) {
        for (i in markersArray) {
            markersArray[i].setMap(null);
        }
    }
}

/**
 * Adds div into Google maps controls.
 * 
 * @param divId id of the div
 */
function addDropDown(divId) {
    var dropdown = document.getElementById(divId);
    map.controls[google.maps.ControlPosition.TOP_RIGHT].push(dropdown);
}

/**** jQuery code starts here ****/

/**
 * Recursively gets locations of all fires via Google maps Geocoding service.
 * 
 * @param i recursive index
 */
function codeAddress(i) {
    //var j=1;        
    /*for (var i = 0; i < allFires.length; i++) {
     console.log(i);
     var address = allFires[i].street + ", " + allFires[i].district + ", Brno";
     
     getXY(i);
     }*/
    var address = allFires[i].street + ", " + allFires[i].district + ", Brno";
    geocoder.geocode({'address': address}, function(results, status) {

        if (status == google.maps.GeocoderStatus.OK) {
            //allFires[i].location = results[0].geometry.location;  --this does not work, do not know why...yet. Next line of code used instead.
            allPositions.push(results[0].geometry.location);
            //allPosition[i]=results[0].geometry.location;
            //$('<div></div>').html(allPositions.length).appendTo('body');
        }
        else {
            //console.log(j); 
            //console.log('nepridane');
            //console.log(address);
            //console.log(status);
            //j++;
            return;

            //console.log(i); 
            //console.log('nepridane');
            //console.log(address);
            //console.log(status);
            //alert('Geocode was not successful for the following reason: ' + status);
        }


        address_position++;
        if (address_position < allFires.length)
        {
            setTimeout(function() {
                codeAddress(address_position);
            }, 1100);
        }
    });
}

/**
 * Wrapper.
 * 
 */
function runJQuery() {
    $(document).ready(load());
}

/**
 * Loads XML file.
 * 
 */
function load() {
    return $.ajax({
        type: "GET",
        url: "fires.xml",
        dataType: "xml"
    }).done(findAll);
}

/**
 * Querys XML file for data.
 * 
 * @param xml xml file
 */
function findAll(xml) {

    $(xml).find("fire").each(function() {

        var obj = new Object();

        obj.time = $(this).find('time').text();
        obj.day = $(this).find('day').text();
        obj.month = $(this).find('month').text();
        obj.year = $(this).find('year').text();
        obj.street = $(this).find('street').text();
        obj.district = $(this).find('district').text();
        obj.description = $(this).find('description').text();
        obj.title = obj.time + ' ' + obj.day + '. ' + obj.month + '. ' + obj.year + ', ' + obj.street;
        obj.content = '<b>' + obj.time + ' ' + obj.day + '. ' + obj.month + '. ' + obj.year + '</b><br/>ulice: ' + obj.street + '</br><p>' + obj.description + '</p>';

        allFires.push(obj);
        //$('<div></div>').html(allFires.length).appendTo('body');	
    });
    codeAddress(0);
}

/**
 * Marks all fires in current district, sets time period
 * 
 */
function markAll() {
    if (period == "a") {
        return;
    }
    period = "a";
    displayDistrict(currentDistrict);
}

/**
 * Marks fires of this month in current district, sets time period
 * 
 */
function markThisMonth() {
    if (period == "m") {
        return;
    }
    fireIndicesByPeriod.length = 0;
    var currentMonth = (new Date()).getMonth() + 1;
    var currentYear = (new Date()).getFullYear();
    for (var i = 0; i < allFires.length; i++) {
        if (currentMonth == allFires[i].month && currentYear == allFires[i].year) {
            fireIndicesByPeriod.push(i);
        }
    }
    period = "m";
    displayDistrict(currentDistrict);
}

/**
 * Marks fires of this year in current district, sets time period
 * 
 */
function markThisYear() {
    if (period == "y") {
        return;
    }
    fireIndicesByPeriod.length = 0;
    var currentYear = (new Date()).getFullYear();
    for (var i = 0; i < allFires.length; i++) {
        if (currentYear == allFires[i].year) {
            fireIndicesByPeriod.push(i);
        }
    }
    period = "y";
    displayDistrict(currentDistrict);
}

/**
 * Marks fires of this week in current district, sets time period
 * 
 */
function markThisWeek() {
    if (period == "w") {
        return;
    }
    fireIndicesByPeriod.length = 0;
    var startDay = 1;
    var now = new Date();
    var d = now.getDay(); //get the current day
    var weekStart = new Date(now.valueOf() - (d <= 0 ? 7 - startDay : d - startDay) * 86400000); //rewind to start day
    var weekEnd = new Date(weekStart.valueOf() + 6 * 86400000); //add 6 days to get last day

    for (var i = 0; i < allFires.length; i++) {
        var fireDate = new Date();
        fireDate.setFullYear(allFires[i].year, allFires[i].month - 1, allFires[i].day);

        if ((weekStart <= fireDate) && (fireDate <= weekEnd)) {
            fireIndicesByPeriod.push(i);
        }
    }
    period = "w";
    displayDistrict(currentDistrict);
}
/**
 * Adds markers to fires of selected district 
 * @param  distr district in which the fires are to be marked
 * 
 */
function markThisDistrict(distr) {
    var multiplier = 1;
    var set = false;

    switch (period) {
        case "a":
            for (var i = 0; i < allFires.length; i++) {
                if (DistrictNames[allFires[i].district] == distr || distr == "all") {
                    addMarker(allPositions[i], allFires[i].title, allFires[i].content);
                }
            }
            break;
        case "y":
            multiplier = 2;
            set = true;
        case "m":
            if (!set) {
                multiplier = 5;
                set = true;
            }
        case "w":
            if (!set) {
                multiplier = 10;
                set = true;
            }
            for (var i = 0; i < fireIndicesByPeriod.length; i++) {
                if (DistrictNames[allFires[fireIndicesByPeriod[i]].district] == distr || distr == "all") {
                    addMarker(allPositions[fireIndicesByPeriod[i]], allFires[fireIndicesByPeriod[i]].title, allFires[fireIndicesByPeriod[i]].content);
                }
            }
            break;
    }

    var color = "00FF00"
    if (markersArray.length * multiplier >= 10) {
        color = "77FF00";
    }
    if (markersArray.length * multiplier >= 15) {
        color = "FFFF00";
    }
    if (markersArray.length * multiplier >= 20) {
        color = "FF7700";
    }
    if (markersArray.length * multiplier >= 25) {
        color = "FF0000";
    }

    selectedDistrict.setOptions({strokeColor: color});
    selectedDistrict.setOptions({fillColor: color});
    if (selectedDistrict == districts["sever1"]) {
        districts["sever2"].setOptions({strokeColor: color});
        districts["sever2"].setOptions({fillColor: color});
    }

//    var aux = new Array();
//    for (var item in DistrictNames) {
//        console.log(item);
//        if (distr == DistrictNames[item] || distr == "all") {
//            aux.push(item);
//        }
//    }
//    var i;
//    var j;
//    var fire=0;
//    if (period == "a") {
//        for (i = 0; i < allFires.length; i++) {
//            for (j = 0; j < aux.length; j++) {
//                if (aux[j] == allFires[i].district) {
//                    addMarker(allPositions[i], allFires[i].title, allFires[i].content);
//                    fire++;
//                }
//            }
//        }
//    }
//    if (period == "y") {
//        for (i = 0; i < yearIndices.length; i++) {
//            for (j = 0; j < aux.length; j++) {
//                if (aux[j] == allFires[yearIndices[i]].district) {
//                    addMarker(allPositions[yearIndices[i]], allFires[yearIndices[i]].title, allFires[yearIndices[i]].content);
//                    fire++;
//                }
//            }
//        }
//    }
//    if (period == "m") {
//        for (i = 0; i < monthIndices.length; i++) {
//            for (j = 0; j < aux.length; j++) {
//                if (aux[j] == allFires[monthIndices[i]].district) {
//                    addMarker(allPositions[monthIndices[i]], allFires[monthIndices[i]].title, allFires[monthIndices[i]].content);
//                    fire++;
//                }
//            }
//        }
//    }
//    if (period == "w") {
//        for (i = 0; i < weekIndices.length; i++) {
//            for (j = 0; j < aux.length; j++) {
//                if (aux[j] == allFires[weekIndices[i]].district) {
//                    addMarker(allPositions[weekIndices[i]], allFires[weekIndices[i]].title, allFires[weekIndices[i]].content);
//                    fire++;
//                }
//            }
//        }
//    }
//    selectedDistrict.setOptions({ fillOpacity: fire/aux.length });
//    if (selectedDistrict==districts["sever1"]){
//        districts["sever2"].setOptions({ fillOpacity: fire/aux.length });
//    }
}


/**
 * Auxiliary function for selecting item in dropdown menu.
 * @param nick district to be displayed
 */
function displayDistrict(nick) {
    deleteOverlays();
    currentDistrict = nick;
    center(nick);
    markThisDistrict(nick);
}

/**** jQuery code ends here ****/

/**
 * Loads necessery data.
 * 
 */
function loadData() {
    pos["all"] = new google.maps.LatLng(49.195054, 16.606843);
    pos["bohunice"] = new google.maps.LatLng(49.170694, 16.582447);
    pos["bosonohy"] = new google.maps.LatLng(49.177327, 16.530105);
    pos["bystrc"] = new google.maps.LatLng(49.228787, 16.526042);
    pos["cernovice"] = new google.maps.LatLng(49.178786, 16.648037);
    pos["chrlice"] = new google.maps.LatLng(49.125904, 16.65559);
    pos["ivanovice"] = new google.maps.LatLng(49.264556, 16.569858);
    pos["jehnice"] = new google.maps.LatLng(49.273965, 16.590359);
    pos["jih"] = new google.maps.LatLng(49.159706, 16.616421);
    pos["jundrov"] = new google.maps.LatLng(49.207515, 16.555201);
    pos["kninicky"] = new google.maps.LatLng(49.255145, 16.49543);
    pos["kohoutovice"] = new google.maps.LatLng(49.192586, 16.545139);
    pos["komin"] = new google.maps.LatLng(49.230266, 16.550375);
    pos["kralovopole"] = new google.maps.LatLng(49.224117, 16.594528);
    pos["lisen"] = new google.maps.LatLng(49.209523, 16.695389);
    pos["malomericeaobrany"] = new google.maps.LatLng(49.227912, 16.651642);//a obrany
    pos["medlanky"] = new google.maps.LatLng(49.241306, 16.567713);
    pos["novyliskovec"] = new google.maps.LatLng(49.17901, 16.555309);
    pos["oresin"] = new google.maps.LatLng(49.28158, 16.6108);
    pos["reckoviceamokrahora"] = new google.maps.LatLng(49.251112, 16.58847);//a mokra hora
    pos["sever"] = new google.maps.LatLng(49.234862, 16.625351);
    pos["slatina"] = new google.maps.LatLng(49.17699, 16.681339);
    pos["staryliskovec"] = new google.maps.LatLng(49.164196, 16.564922);
    pos["stred"] = new google.maps.LatLng(49.192466, 16.605168);
    pos["turany"] = new google.maps.LatLng(49.147693, 16.667669);
    pos["utechov"] = new google.maps.LatLng(49.286647, 16.633766);
    pos["vinohrady"] = new google.maps.LatLng(49.206944, 16.662899);
    pos["zabovresky"] = new google.maps.LatLng(49.213691, 16.574814);
    pos["zebetin"] = new google.maps.LatLng(49.205149, 16.491825);
    pos["zidenice"] = new google.maps.LatLng(49.196625, 16.642029);



    districts["bohunice"] = BrnoBohunice;
    districts["bosonohy"] = BrnoBos;
    districts["bystrc"] = BrnoBys;
    districts["cernovice"] = BrnoCer;
    districts["chrlice"] = BrnoChrl;
    districts["ivanovice"] = BrnoIvan;
    districts["jehnice"] = BrnoJeh;
    districts["jih"] = BrnoJih;
    districts["jundrov"] = BrnoJund;
    districts["kninicky"] = BrnoKni;
    districts["kohoutovice"] = BrnoKoh;
    districts["komin"] = BrnoKomin;
    districts["kralovopole"] = BrnoKrpol;
    districts["lisen"] = BrnoLis;
    districts["malomericeaobrany"] = BrnoMaO;
    districts["medlanky"] = BrnoMed;
    districts["novyliskovec"] = BrnoNovLis;
    districts["oresin"] = BrnoOre;
    districts["reckoviceamokrahora"] = BrnoRaMh;
    districts["sever1"] = BrnoS1;//2 separate map regions
    districts["sever2"] = BrnoS2;//2 separate map regions
    districts["slatina"] = BrnoSlat;
    districts["staryliskovec"] = BrnoStLis;
    districts["stred"] = BrnoStred;
    districts["turany"] = BrnoTur;
    districts["utechov"] = BrnoUte;
    districts["vinohrady"] = BrnoVino;
    districts["zabovresky"] = BrnoZab;
    districts["zebetin"] = BrnoZeb;
    districts["zidenice"] = BrnoZide;
}
